/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/

// 实现Promise源码
// 1.Promise接受一个函数 并立即执行 该函数有两个参数是两个方法--用来决定Promise的最终状态
// 2.状态有三种pending, fulfilled, rejected 状态一旦确定 无法改变
// 3.异步和同步中的then方法处理不同,且then可以多次调用
// 4.then方法可以链式调用获取上一个then中回调函数返回的的值,then方法返回一个Promise
// 5.回调函数可能返回一个Promise，下一个then就是该Promise的then方法，注意该promsie不能返回自己
// 6.all静态方法的实现：返回一个保存结果的数组，有一个部分失败就返回reject
// 7.Promise.resolve将给定的值转换为promise对象，返回一个promise对象，
// 8.finally方法 返回一个promise，且无论当前promise返回成功或失败都会执行
// 9.catch方法 当then中失败回调不执行时 会在catch中捕获
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class myPromise{
    constructor(executor){
        executor(this.resolve, this.reject)
    }
    status = PENDING
    value = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = (value) => {
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.value = value
        while(this.successCallback.length){
            this.successCallback.shift()()
        }
    }
    reject = (reason) => {
        if(this.status !== PENDING) return
        this.status = REJECTED
        this.reason = reason
        while(this.failCallback.length){
            this.failCallback.shift()()
        }
    }
    then(successCallback, failCallback){
        let promise2 = new myPromise((resolve, reject)=>{
            setTimeout(()=>{
                if(this.status === FULFILLED){
                    try {//promise2的使用:添加setTimeout使其为异步代码，执行时promise2已经定义完成
                        let x = successCallback(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {//运行期间报错时 第二个promsie走reject
                        reject(error)
                    }
                    
                }else if(this.status === REJECTED){
                    try {
                        let x = failCallback(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                   
    
                }else{ //异步时 status=PENDIGN，异步执行完成后再执行回调
                    // this.successCallback = successCallback
                    this.successCallback.push(()=>{
                        try {
                            let x = successCallback(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }                  
                    })
                    
                    this.failCallback.push(() => {
                        try {
                            let x = failCallback(this.reason)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                           reject(error) 
                        }
                        
                    })
                }

            },0)
        })
        return promise2
    }
    finally(callback){
        //获取当前promise的状态
       return this.then((value)=>{//当前Promsie状态 成功，
         console.log('value=',value)
           return myPromise.resolve(callback()).then(()=> value)
         //   callback();
         //   return value//拿到调用他的promsie的值
         },(reason)=>{
             // callback();
             // return reason//
            return myPromise.resolve(callback()).then(()=>{throw reason})
         })}
    static all(arr){
        return new myPromise((resolve, reject) => {
            let result = []
            let count = 0
            function addData (i, value){
                count++;
                result[i] = value
                if(count == arr.length) resolve(result)
            }
            for(let i = 0; i < arr.length; i ++){
                let current = arr[i]
                if(current instanceof myPromise){
                    current.then(value => {addData(i,value)}, reason => reject(reason))
                    
                }else{
                    addData(i,current)
                }
            }
            // resolve(result)
        })
    }
    static resolve(value){
    // 值为promise对象则把该对象作为resolve方法的返回值
        if(value instanceof myPromise) return value

        return new myPromise((resolve)=> resolve(value))     
    }
    catch(callback){//
      return this.then(undefined, callback)
    }
    
}
function resolvePromise(promise2,x,resolve, reject){
    if(promise2 === x) {
        reject('循环调用')
    }
    if(x instanceof myPromise){
        x.then(value=>{
            resolve(value)
        },reason=>{
            reject(reason)
        })
    }else{
        resolve(x)
    }
}



//用例
let p = new myPromise(function(resolve, reject){
    setTimeout(()=>{
        resolve('成功')
    }, 1000)
    // resolve('成功')
})

let p1 = new myPromise((resolve)=>{
    resolve('p2 resolve')
})

p1.finally(()=>{
console.log('finally')
return p
}).then(value =>{
    console.log(value)
})

// myPromise.resolve(10).then(value=>{
//     console.log(value)
// })
// myPromise.resolve(p).then(value =>{
//     console.log(value)
// })
// let pp = myPromise.all(['a', p, p1, 'b']).then(value =>{
//     console.log('pp ',value)
// })
// 


// p.then((value)=>{
//     console.log(value)
//     return p1
// },reason =>{ 
//     console.log(reason)
//     return '200'
// }).then(value => {
//     console.log( 'then value-',value)
// })